<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>啊是大苏打</title>
    <link rel="stylesheet" type="text/css" href="plugin/webuploader-0.1.5/webuploader.css">
    <script type="text/javascript" src="js/jquery.min.js"></script>
    <script type="text/javascript" src="plugin/webuploader-0.1.5/webuploader.js"></script>

</head>
<body>
    <button id="picker">选择文件</button>
    <button id="up">开始上传</button>
    <button id="start">继续</button>
    <button id="stop">停止</button>

    <div>
        <div>
            <span id="percentage">0%</span>
        </div>
        <div id="logdiv">

        </div>
    </div>


</body>
<script type="text/javascript">
    var file_md5   = null;   //这个文件的MD5,用于去服务器校验是否有这个文件
    var chunk_md5 = null;    //单个文件块的MD5,用于文件快上传后的校验,看看是否是完整的文件快
    var secSend = false;     //是否秒传,如果服务器存在这个文件,就可以开启秒传,欺骗一下客户,其实没有传,只是做个样子.
    var uploader;            //控件
    var file_chunks;         //一共有多少个文件块
    WebUploader.Uploader.register({
    //文件发送之前执行,整个文件发送之前
    "before-send-file":"beforeSendFile",
    //文件块发送之前在文件分片（如果没有启用分片，整个文件被当成一个分片）后，上传之前执行
    "before-send":"beforeSend",
    //在文件所有分片都上传完后，且服务端没有错误返回后执行
    "after-send-file":"afterSendFile"
    },{
        beforeSendFile:function(file) {
            //是js的一个异步处理,具体的不太懂
            var  deferred = WebUploader.Deferred();
            log("正在计算MD5值...");
            //uploader的计算md5的方法
            uploader.md5File(file,0,2*1024*1024).progress(function(percentage) {
                //这里是MD5 的计算进度
                log("md5计算进度"+(percentage*100).toFixed()+'%');
            }).then(
                  //计算完成后的处理逻辑
                  function(fileMd5) {
                        //我们把这个MD5的值缓存起来,以便以后使用
                        file_md5 = fileMd5;
                        log("MD5计算完成:"+fileMd5);
                        console.log("file_md5:"+file_md5);
                        // 检查是否有已经上传成功的分片文件
                        $.post('/checkfile', {filemd5: file_md5}, function (result) {
                            console.log(result);
                            // 如果有对应的文件，推入数组
                            //这个result是自己定义的一个json返回结果
                            if (result.data==true) {
                                //如果根据文件的MD5判断文件存在,那就跳过文件上传,如果需要的话,这里也可以返回具体的文件的路径.以便使用.
                                uploader.skipFile(file);
                                //把秒传设置为true
                                secSend = true;
                            }
                            //这个不太懂.貌似是js的异步的执行的意思.
                            deferred.resolve();
                        });
                  }
            );
            //这个也是js的特性
            return deferred.promise();
        },
        beforeSend:function (block) {
            var deferred = WebUploader.Deferred();
            file_chunks = block.chunks;
            var chunksize = block.end-block.start;
            $.post('/checkchunk', { "filemd5": file_md5, "chunk": block.chunk,"chunksize":chunksize }, function (data) {
                log("分块_"+block.chunk+"状态:"+data.msg);
                if(data.data==true) {
                    // 分块存在，跳过该分块
                    deferred.reject();
                } else {
                    // 分块不存在或不完整，重新发送
                    deferred.resolve();
                }
            });
            return deferred.promise();
        },
        afterSendFile:function(file) {
            var deferred = WebUploader.Deferred();
            //判断是否秒传
            if(!secSend){
                $.post('/merge', { filemd5: file_md5, filename: file.name }, function (data) {
                    if(data.code==0){
                        console.log("合并成功")
                    }else {
                        console.log("合并失败")
                    }
                    log(data.msg);
                    deferred.resolve();
                });
            }else {
                deferred.resolve();
            }
            return deferred.promise();
        }
    });


    // 创建上传
    uploader = WebUploader.create({
        swf: '/plugin/webuploader-0.1.5/Uploader.swf',
        server: '/upload',          // 服务端地址
        pick: '#picker',              // 指定选择文件的按钮容器
        resize: false,
        chunked: true,                //开启分片上传
        chunkSize: 1024 * 1024 * 5,   //每一片的大小
        chunkRetry: 3,              // 如果遇到网络错误,重新上传次数
        threads: 3,                   // [默认值：3] 上传并发数。允许同时最大上传进程数。
    });

    // 上传提交
    $("#up").click(function () {
        log('准备上传...');
        uploader.upload();
    });


    // 当有文件被添加进队列的时候-md5序列化
    uploader.on('fileQueued', function (file) {
        log(file.name+"等待上传...");
    });


    // 发送前在body中添加一些信息，如分块数目chunks
    uploader.on('uploadBeforeSend', function( block, data ) {
        //事件里不支持这种用法
        data.chunks = block.chunks;
        data.chunk = block.chunk;
        data.chunkmd5 = chunk_md5;
        data.filemd5 = file_md5;
    });

    // 上传完成后触发
    uploader.on('uploadSuccess', function (file,response) {
        $("#percentage").text("100%")
        log("上传完成");
    });

    // 文件上传过程中创建进度条实时显示。
    uploader.on('uploadProgress', function (file, percentage) {
        $("#percentage").html(parseInt(percentage * 100) +"%");
    });
    // 上传出错处理
    uploader.on('uploadError', function (file) {
        uploader.retry();
    });
    // 暂停处理
    $("#stop").click(function(e){
        log("暂停上传...");
        uploader.stop(true);
    });

    // 从暂停文件继续
    $("#start").click(function(e){
        log("恢复上传...");
        uploader.upload();
    });


    function log(str) {
        $("#logdiv").append(str).append("</br>")
    };
    </script>
</html>